package com.by.log;

import com.by.log.constants.LogLevel;
import com.by.log.entity.LogEntry;
import com.by.log.handler.DefaultLogStorage;
import com.by.log.handler.LogStorage;
import com.by.log.handler.LoggerProvider;
import com.by.log.provider.DefaultLoggerProvider;
import com.by.log.config.LogProperties;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.Map;
import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentHashMap;

@Data
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class LoggerFactory {
    private static final Map<String, Logger> LOGGER_CACHE = new ConcurrentHashMap<>();
    private static volatile LoggerProvider loggerProvider;
    private static volatile LogStorage logStorage;
    /**
     * -- GETTER --
     *  获取当前刷盘模式
     */
    @Getter
    private static volatile boolean asyncMode = true; // 默认异步模式

    // 默认日志文件路径
    private static volatile String defaultLogFilePath = "./logs/miaosha.log";
    
    private static LogProperties logProperties = new LogProperties();

    // 静态初始化，加载配置和Provider
    static {
        initProviders();
        initStorages();
    }

    /**
     * 初始化日志提供者（通过SPI）
     */
    private static void initProviders() {
        try {
            ServiceLoader<LoggerProvider> serviceLoader = ServiceLoader.load(LoggerProvider.class);
            for (LoggerProvider provider : serviceLoader) {
                loggerProvider = provider;
                System.out.println("Loaded LoggerProvider: " + provider.getClass().getName());
                return;
            }
            System.out.println("Failed to load LoggerProvider via SPI, using default");
            loggerProvider = new DefaultLoggerProvider();
        } catch (Exception e) {
            System.out.println("Failed to load LoggerProvider via SPI, using default: " + e.getMessage());
            loggerProvider = new DefaultLoggerProvider();
        }
    }

    /**
     * 初始化存储策略（根据模式选择同步/异步）
     */
    private static void initStorages() {
        try {
            ServiceLoader<LogStorage> serviceLoader = ServiceLoader.load(LogStorage.class);
            for (LogStorage storage : serviceLoader) {
                logStorage = storage;
                System.out.println("Loaded LogStorage: " + storage.getClass().getName());
                return;
            }
            System.out.println("Failed to load LogStorage via SPI, using default");
            logStorage = new DefaultLogStorage(
                logProperties.getDefaultLogFilePath() != null ? logProperties.getDefaultLogFilePath() : defaultLogFilePath, 
                logProperties.isAsyncMode());
        } catch (Exception e) {
            System.out.println("Failed to load LogStorage via SPI, using default: " + e.getMessage());
            logStorage = new DefaultLogStorage(
                logProperties.getDefaultLogFilePath() != null ? logProperties.getDefaultLogFilePath() : defaultLogFilePath, 
                logProperties.isAsyncMode());
        }
    }

    /**
     * 根据类获取日志实例
     */
    public static Logger getLogger(Class<?> clazz) {
        return getLogger(clazz.getName());
    }

    /**
     * 根据类名获取日志实例
     */
    public static Logger getLogger(String className) {
        return LOGGER_CACHE.computeIfAbsent(className, name -> 
                loggerProvider.getLogger(name, logStorage)
        );
    }

    /**
     * 设置刷盘模式（同步/异步）
     *
     * @param async 是否启用异步模式
     */
    public static void setAsyncMode(boolean async) {
        if (asyncMode != async) {
            asyncMode = async;
            // 注意：这里无法重新初始化存储，因为缺少Spring上下文
        }
    }

    /**
     * 关闭日志框架，释放资源
     */
    public static void shutdown() {
        try {
            if (logStorage != null) {
                logStorage.shutdown();
            }
            LOGGER_CACHE.clear();
        } catch (Exception e) {
            System.err.println("Failed to shutdown logger factory: " + e.getMessage());
        }
    }

    /**
     * 创建日志上下文（用于RPC链路追踪）
     */
    public static LogEntry createLogContext(String serviceName) {
        LogEntry context = new LogEntry();
        context.setServiceName(serviceName);
        context.setThreadName(Thread.currentThread().getName());
        context.setThreadId(Thread.currentThread().getId());
        return context;
    }

    /**
     * 设置默认日志文件路径
     * @param filePath 日志文件路径
     */
    public static void setDefaultLogFilePath(String filePath) {
        defaultLogFilePath = filePath;
        // 注意：这里无法重新初始化存储，因为缺少Spring上下文
    }
    
    /**
     * 设置日志配置属性
     * @param properties 日志配置属性
     */
    public static void setLogProperties(LogProperties properties) {
        if (properties != null) {
            logProperties = properties;
            // 更新默认值
            if (properties.getDefaultLogFilePath() != null) {
                defaultLogFilePath = properties.getDefaultLogFilePath();
            }
            asyncMode = properties.isAsyncMode();
        }
    }
    
    /**
     * 获取当前日志配置属性
     * @return 日志配置属性
     */
    public static LogProperties getLogProperties() {
        return logProperties;
    }
}